package com.cygsunri.consumption.service;

import com.alibaba.fastjson.JSONObject;
import com.cygsunri.common.constant.DataName;
import com.cygsunri.common.constant.DevicePsrId;
import com.cygsunri.common.service.CommonDataService;
import com.cygsunri.consumption.entity.Branch;
import com.cygsunri.consumption.entity.Building;
import com.cygsunri.consumption.entity.EnergyItem;
import com.cygsunri.consumption.entity.enumerate.EnergySort;
import com.cygsunri.measurement.entity.Flag;
import com.cygsunri.measurement.entity.MeasurementValue;
import com.cygsunri.rbac.entity.Account;
import com.cygsunri.scada.service.ScadaMeasurementService;
import com.cygsunri.template.entity.psr.DeviceTemplateData;
import com.cygsunri.template.service.DeviceTemplateDataService;
import com.cygsunri.util.DateUtil;
import com.cygsunri.util.TimeUtil;
import com.github.abel533.echarts.Option;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class ConsumptionService {

    @Autowired
    private CommonDataService commonDataService;
    @Autowired
    private ScadaMeasurementService scadaMeasurementService;
    @Autowired
    private DeviceTemplateDataService deviceTemplateDataService;
    @Autowired
    private BranchService branchService;

    /**
     * 获取能耗统计JSON
     * @param account 用户
     * @param energySort 能耗类型
     */
    public JSONObject getAllConversionEnergy(Account account, EnergySort energySort) {
        JSONObject object = new JSONObject(true);
        ImmutablePair<String, Integer> pair = scadaMeasurementService.getMeasurementID(account.getPsrID(), energySort.getName());
        if (pair == null) {
            return object;
        }
        DeviceTemplateData deviceTemplateData = deviceTemplateDataService.getDeviceTemplateDataByPsrIDAndName(account.getPsrID(), energySort.getName());
        object.put("energyCode", energySort.getName());
        object.put("energyDesc", energySort.getDesc());
        object.put("energyUnit", deviceTemplateData.getUnit());
        Double dayEconomize = 0d, monthEconomize = 0d, yearEconomize = 0d;
        Double slope;
        if (energySort.getKey() == 0) {
            List<Branch> airBranches = branchService.getBranchesByEnergyItem("Air");
            Double airDay = 0d, airMonth = 0d, airYear = 0d;
            for (Branch branch : airBranches) {
                MeasurementValue day = commonDataService.getValue(branch.getPsrID(), DataName.ELECTRICITY, DateUtil.nowMilliSeconds(), Flag.DAY_DIFF);
                if (!day.isInValid()) {
                    airDay += day.getData();
                }
                MeasurementValue month = commonDataService.getValue(branch.getPsrID(), DataName.ELECTRICITY, DateUtil.nowMilliSeconds(), Flag.MONTH_DIFF);
                if (!month.isInValid()) {
                    airMonth += month.getData();
                }
                MeasurementValue year = commonDataService.getValue(branch.getPsrID(), DataName.ELECTRICITY, DateUtil.nowMilliSeconds(), Flag.YEAR_DIFF);
                if (!year.isInValid()) {
                    airYear += year.getData();
                }
            }

            List<Branch> lightingBranches = branchService.getBranchesByEnergyItem("Lighting");
            Double lightingDay = 0d, lightingMonth = 0d, lightingYear = 0d;
            for (Branch branch : lightingBranches) {
                MeasurementValue day = commonDataService.getValue(branch.getPsrID(), DataName.ELECTRICITY, DateUtil.nowMilliSeconds(), Flag.DAY_DIFF);
                if (!day.isInValid()) {
                    lightingDay += day.getData();
                }
                MeasurementValue month = commonDataService.getValue(branch.getPsrID(), DataName.ELECTRICITY, DateUtil.nowMilliSeconds(), Flag.MONTH_DIFF);
                if (!month.isInValid()) {
                    lightingMonth += month.getData();
                }
                MeasurementValue year = commonDataService.getValue(branch.getPsrID(), DataName.ELECTRICITY, DateUtil.nowMilliSeconds(), Flag.YEAR_DIFF);
                if (!year.isInValid()) {
                    lightingYear += year.getData();
                }
            }

            //用户给的公式
            dayEconomize = airDay * 0.15 + lightingDay * 0.05;
            monthEconomize = airMonth * 0.15 + lightingMonth * 0.05;
            yearEconomize = airYear * 0.15 + lightingYear * 0.05;
            //用户给的系数
            slope = 0.000326;
        } else {
            MeasurementValue day = commonDataService.getValue(DevicePsrId.CONSUMPTION, DataName.WATER, DateUtil.nowMilliSeconds(), Flag.DAY_DIFF);
            MeasurementValue month = commonDataService.getValue(DevicePsrId.CONSUMPTION, DataName.WATER, DateUtil.nowMilliSeconds(), Flag.MONTH_DIFF);
            MeasurementValue year = commonDataService.getValue(DevicePsrId.CONSUMPTION, DataName.WATER, DateUtil.nowMilliSeconds(), Flag.YEAR_DIFF);
            //用户给的公式
            dayEconomize = day.isInValid() ? 0 : day.getData() * 0.13;
            monthEconomize = month.isInValid() ? 0 : month.getData() * 0.13;
            yearEconomize = year.isInValid() ? 0 : year.getData() * 0.13;
            //用户给的系数
            slope = 0.0002429;
        }

        //当日
        MeasurementValue todayV = commonDataService.getValue(pair.getLeft(), DateUtil.nowMilliSeconds(), Flag.DAY_DIFF);
        object.put("today", todayV.isInValid() ? "-" : todayV.getData());
        //昨日
        MeasurementValue lastDayV = commonDataService.getValue(pair.getLeft(), DateUtil.lastDay(), Flag.DAY_DIFF);
        object.put("lastDay", lastDayV.isInValid() ? "-" : lastDayV.getData());
        //日同比
        MeasurementValue lastYearDayV = commonDataService.getValue(pair.getLeft(), TimeUtil.toMilliSeconds(LocalDateTime.now().minusYears(1)), Flag.DAY_DIFF);
        object.put("dayYoyAnalysis", todayV.isInValid() || lastYearDayV.isInValid() || lastYearDayV.getData() == 0d ? "-" : 100 * (todayV.getData() - lastYearDayV.getData()) / lastYearDayV.getData());
        //日环比
        object.put("dayChainAnalysis", todayV.isInValid() || lastDayV.isInValid() || lastDayV.getData() == 0d ? "-" : 100 * (todayV.getData() - lastDayV.getData()) / lastDayV.getData());
        //标准煤
        object.put("dayCoalConversion", todayV.isInValid() ? "-" : todayV.getData() * slope);
        //节约能耗
        object.put("dayEnergySaving", dayEconomize < 0 ? 0 : dayEconomize);
        //节约能耗标准煤
        object.put("dayEnergySavingCoal", dayEconomize < 0 ? 0 : dayEconomize * slope);

        //当月
        MeasurementValue thisMonthV = commonDataService.getValue(pair.getLeft(), DateUtil.nowMilliSeconds(), Flag.MONTH_DIFF);
        object.put("thisMonth", thisMonthV.isInValid() ? "-" : thisMonthV.getData());
        //上月
        MeasurementValue lastMonthV = commonDataService.getValue(pair.getLeft(), DateUtil.lastMonth(), Flag.MONTH_DIFF);
        object.put("lastMonth", lastMonthV.isInValid() ? "-" : lastMonthV.getData());
        //月同比
        MeasurementValue lastYearMonthV = commonDataService.getValue(pair.getLeft(), TimeUtil.toMilliSeconds(LocalDateTime.now().minusYears(1)), Flag.MONTH_DIFF);
        object.put("monthYoyAnalysis", thisMonthV.isInValid() || lastYearMonthV.isInValid() || lastYearMonthV.getData() == 0d ? "-" : 100 * (thisMonthV.getData() - lastYearMonthV.getData()) / lastYearMonthV.getData());
        //月环比
        object.put("monthChainAnalysis", thisMonthV.isInValid() || lastMonthV.isInValid() || lastMonthV.getData() == 0d ? "-" : 100 * (thisMonthV.getData() - lastMonthV.getData()) / lastMonthV.getData());
        //标准煤
        object.put("monthCoalConversion", thisMonthV.isInValid() ? "-" : thisMonthV.getData() * slope);
        //节约能耗
        object.put("monthEnergySaving", monthEconomize < 0 ? 0 : monthEconomize);
        //节约能耗标准煤
        object.put("monthEnergySavingCoal", monthEconomize < 0 ? 0 : monthEconomize * slope);

        //今年
        MeasurementValue thisYearV = commonDataService.getValue(pair.getLeft(), DateUtil.nowMilliSeconds(), Flag.YEAR_DIFF);
        object.put("thisYear", thisYearV.isInValid() ? "-" : thisYearV.getData());
        //去年
        MeasurementValue lastYearV = commonDataService.getValue(pair.getLeft(), TimeUtil.toMilliSeconds(DateUtil.lastYear(LocalDateTime.now())), Flag.YEAR_DIFF);
        object.put("lastYear", lastYearV.isInValid() ? "-" : lastYearV.getData());
        //年同比
        object.put("yearYoyAnalysis", "-");
        //年环比
        object.put("yearChainAnalysis", thisYearV.isInValid() || lastYearV.isInValid() || lastYearV.getData() == 0d ? "-" : 100 * (thisYearV.getData() - lastYearV.getData()) / lastYearV.getData());
        //标准煤
        object.put("yearCoalConversion", thisYearV.isInValid() ? "-" : thisYearV.getData() * slope);
        //节约能耗
        Double yearEnergySaving = thisYearV.isInValid() || lastYearV.isInValid() ? Double.NaN : lastYearV.getData() - thisYearV.getData();
        object.put("yearEnergySaving",yearEconomize < 0 ? 0 : yearEconomize);
        //节约能耗标准煤
        object.put("yearEnergySavingCoal", yearEconomize < 0 ? 0 : yearEconomize * slope);
        return object;
    }

    /**
     * 能耗对比-获取分项option
     */
    public Option handleEnergyItemOption(Option option, Account account, List<EnergyItem> energyItems, String energySort, List<String> times, int flag) {
        for (String time : times) {
            option.getxAxis().get(0).data(time);
            Double itemTotal = 0d;
            int i = 0;
            for (EnergyItem energyItem : energyItems) {
                List<Branch> branches = branchService.getBranchesByAccountAndEnergyItem(account.getId(), energyItem.getId());

                Double sum = 0d;
                for (Branch branch : branches) {
                    MeasurementValue m = commonDataService.getValue(branch.getPsrID(), energySort, TimeUtil.toMilliSeconds(time), flag);
                    sum += m.isInValid() ? 0d : m.getData();
                }
                itemTotal += sum;
                option.getSeries().get(i).data(sum);
                i++;
            }

            MeasurementValue total = commonDataService.getValue(account.getPsrID(), energySort, TimeUtil.toMilliSeconds(time), flag);
            Double other = total.isInValid() ? 0d : total.getData() - itemTotal;
            option.getSeries().get(i).data(other);

            option.getSeries().get(i + 1).data(total.isInValid() ? "-" : total.getData());

            String period = DateUtil.getPeriodTime(time);
            if (period == null) {
                option.getSeries().get(i + 2).data("-");
            } else {
                MeasurementValue beforeDayTotal = commonDataService.getValue(account.getPsrID(), energySort, TimeUtil.toMilliSeconds(period), flag);
                option.getSeries().get(i + 2).data(beforeDayTotal.isInValid() ? "-" : beforeDayTotal.getData());
            }
        }
        return option;
    }

    /**
     * 能耗对比-获取建筑option
     */
    public Option handleBuildingOption(Option option, Account account, List<Building> buildings, String energySort, List<String> times, int flag) {
        for (String time : times) {
            option.getxAxis().get(0).data(time);
            Double itemTotal = 0d;
            int i = 0;
            for (Building building : buildings) {
                MeasurementValue m = commonDataService.getValue(building.getPsrID(), energySort, TimeUtil.toMilliSeconds(time), flag);
                itemTotal += m.isInValid() ? 0d : m.getData();
                option.getSeries().get(i).data(m.isInValid() ? "-" : m.getData());
                i++;
            }

            MeasurementValue total = commonDataService.getValue(account.getPsrID(), energySort, TimeUtil.toMilliSeconds(time), flag);
            Double other = total.isInValid() ? 0d : total.getData() - itemTotal;
            option.getSeries().get(i).data(other);

            option.getSeries().get(i + 1).data(total.isInValid() ? "-" : total.getData());

            String period = DateUtil.getPeriodTime(time);
            if (period == null) {
                option.getSeries().get(i + 2).data("-");
            } else {
                MeasurementValue beforeDayTotal = commonDataService.getValue(account.getPsrID(), energySort, TimeUtil.toMilliSeconds(period), flag);
                option.getSeries().get(i + 2).data(beforeDayTotal.isInValid() ? "-" : beforeDayTotal.getData());
            }
        }
        return option;
    }


}
